package com.lagou.edu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.logging.SimpleFormatter;

@Controller
@RequestMapping("demo")
public class DemoController {

    //springMVC的异常处理机制（异常处理器）
    //注意：写在这里只会对当前controller类生效
    /*@ExceptionHandler(ArithmeticException.class)
    public void handleException(ArithmeticException exception, HttpServletResponse response) {
        //异常处理逻辑
        try {
            response.getWriter().write(exception.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }*/

    /**
     * url: http://localhost:8080/demo/handle01
     */
    @RequestMapping("handle01")
    public ModelAndView handle01(@ModelAttribute("name") String name) {
        //int c = 1 / 0;
        //服务器时间
        Date date = new Date();
        //返回服务器时间到前端页面
        //封装了数据和页面信息的ModelAndView
        ModelAndView modelAndView = new ModelAndView();
        //addObject其实是向请求域中request.setAttribute("date", date);
        modelAndView.addObject("date", date);
        //视图信息(封装跳转的页面信息) 逻辑视图名
        modelAndView.setViewName("success");
        return modelAndView;
    }

    /**
     * SpringMVC在handler方法上传入Map、Model和ModelMap参数，并向这些参数中保存数据（放入到请求域），都可以在页面获取到
     *
     * 它们之间是什么关系？
     * 运行时的具体类型都是BindingAwareModelMap，相当于给BindingAwareModelMap中保存的数据都会放在请求域中
     *
     * Map（jdk中的接口）     Model（spring的接口）
     * ModelMap（class，实现Map接口）
     * BindingAwareModelMap继承了ExtendedModelMap，ExtendedModelMap继承了ModelMap，实现了Model
     */

    /**
     * 直接声明形参ModelMap，封装数据
     * url: http://localhost:8080/demo/handle11
     */
    @RequestMapping("handle11")
    public String handle11(ModelMap modelMap) {
        Date date = new Date();
        modelMap.addAttribute("date", date);
        System.out.println("==============ModelMap:" + modelMap.getClass());
        return "success";
    }

    /**
     * 直接声明形参Model，封装数据
     * url: http://localhost:8080/demo/handle12
     */
    @RequestMapping("handle12")
    public String handle12(Model model) {
        Date date = new Date();
        model.addAttribute("date", date);
        System.out.println("==============Model:" + model.getClass());
        return "success";
    }

    /**
     * 直接声明形参Map集合，封装数据
     * url: http://localhost:8080/demo/handle13
     */
    @RequestMapping("handle13")
    public String handle13(Map<String, Object> map) {
        Date date = new Date();
        map.put("date", date);
        System.out.println("==============Map:" + map.getClass());
        return "success";
    }

    /**
     * 文件上传
     */
    @RequestMapping("upload")
    public ModelAndView upload(MultipartFile uploadFile, HttpSession session) throws IOException {

        //处理上传文件
        //重命名，原名123.jpg，获取后缀
        //原始名称
        String originalFilename = uploadFile.getOriginalFilename();
        //扩展名 jpg
        String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1, originalFilename.length());
        String newName = UUID.randomUUID().toString() + "." + ext;

        //存储，要存储到指定的文件夹，/uploads/yyyy-MM-dd，考虑文件过多的情况：按照日期，生成一个子文件夹
        String realPath = session.getServletContext().getRealPath("uploads");
        String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        File folder = new File(realPath + "/" + datePath);
        if (!folder.exists()) {
            folder.mkdirs();
        }

        //存储文件到目录
        uploadFile.transferTo(new File(folder, newName));

        //TODO 文件磁盘路径要更新到数据库字段

        Date date = new Date();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("date", date);
        modelAndView.setViewName("success");
        return modelAndView;
    }

    /**
     * SpringMVC 重定向时参数传递问题
     * 转发：A找B借钱400，B没有钱，但是悄悄找到C借了400块钱给A
     *      url不会变，参数也不会丢失，是一个请求
     * 重定向：A找B借钱400，B说我没有钱，你找别人借去吧，于是A又带着400块钱的借钱需求找到C
     *      url会变，参数会丢失，需要重新携带参数，是两个请求
     */
    @RequestMapping("/handleRedirect")
    public String handleRedirect(String name, RedirectAttributes redirectAttributes) {
        //return "redirect:handle01?name=" + name; //拼接：参数安全性，参数长度都有局限

        //addFlashAttribute方法设置了一个flash类型的属性，该属性会被暂存到session中，在跳转到页面之后该属性销毁
        redirectAttributes.addFlashAttribute("name", name);
        return "redirect:handle01";
    }
}
